package org.artifact.core.server;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.artifact.core.lang.AbstractPlugin;

import java.util.*;

/**
 * 插件
 *
 * @author apple
 */
@SuppressWarnings("unchecked")
public class ServerPlugins {

    static final Log log = LogFactory.get(ServerPlugins.class);

    private ServerPlugins() {
    }

    private static ServerPlugins ME = new ServerPlugins();

    public static ServerPlugins me() {
        return ME;
    }

    private final Map<String, AbstractPlugin> plugins = new LinkedHashMap<>();


    /**
     * 添加插件
     */
    public ServerPlugins load(AbstractPlugin plugin) {
        String pluginKey = plugin.getClass().getName();
        if (pluginKey == null) {
            throw new IllegalArgumentException("plugin name can not be null");
        }
        if (plugins.containsKey(pluginKey)) {
            throw new IllegalArgumentException("this plugin name existed");
        }
        plugins.put(pluginKey, plugin);
        return this;
    }

    public <T> T getPlugin(Class<T> clazz) {
        return (T) plugins.get(clazz.getName());
    }


    public void start() {
        if (plugins.isEmpty()) {
            return;
        }

        List<AbstractPlugin> startPlugins = CollUtil.sort(plugins.values(), (p1, p2) -> Integer.compare(p1.getStartIndex(), p2.getStartIndex()));

        startPlugins.forEach(v -> {
            try {
                boolean status = v.start();
                if (!status) {
                    String msg = "Start Plugin [" + v.getClass().getName() + "] Error";
                    throw new RuntimeException(msg);
                }
                log.debug("Start Plugin [{}] Success",v.getClass().getName());
            } catch (Exception e) {
                String msg = "Start Plugin [" + v.getClass().getName() + "] Error";
                e.printStackTrace();
                throw new RuntimeException(msg);
            }
        });
    }

    public void stop() {
        if (plugins.isEmpty()) {
            return;
        }

        List<AbstractPlugin> stopPlugins = CollUtil.sort(plugins.values(), (p1, p2) -> Integer.compare(p1.getStopIndex(), p2.getStopIndex()));

        stopPlugins.forEach(v -> {
            try {
                boolean status = v.stop();
                if (!status) {
                    String msg = "Stop Plugin [" + v.getClass().getName() + "] Error";
                    throw new RuntimeException(msg);
                }
                log.debug("Stop Plugin [{}] Success",v.getClass().getName());
            } catch (Exception e) {
                String msg = "Stop Plugin [" + v.getClass().getName() + "] Error";
                e.printStackTrace();
                throw new RuntimeException(msg);
            }
        });
    }
}
